from abc import ABCMeta
from dataclasses import dataclass, field
from typing import Union

import yaml
from dataclasses_json import DataClassJsonMixin
from pathlib import Path
from yamldataclassconfig import create_file_path_field, build_path


@dataclass
class YamlDataClassConfig(DataClassJsonMixin, metaclass=ABCMeta):
    def load(self, path: Union[Path, str], path_is_absolute: bool = False):
        """
        This method loads from YAML file to properties of self instance.
        Why doesn't load when __init__ is to make the following requirements compatible:
        1. Access config as global
        2. Independent on config for development or use config for unit testing when unit testing
        """
        built_path = build_path(path, path_is_absolute)
        # pylint: disable=no-member
        with built_path.open('r', encoding='UTF-8') as yml:
            dictionary_config = yaml.full_load(yml)
        self.__dict__.update(self.__class__.schema().load(dictionary_config).__dict__)


@dataclass
class WeixinConfig(DataClassJsonMixin):
    app_id: str = None
    secret: str = None
    token: str = None

    register_secret: str = None
    root_name: str = None


@dataclass
class DbConfig(DataClassJsonMixin):
    url: str = None


@dataclass
class WebConfig(DataClassJsonMixin):
    secret: str = None
    secret_hours: int = 24 * 10


@dataclass
class BaiduConfig(DataClassJsonMixin):
    map_ak: str = None


@dataclass
class Settings(YamlDataClassConfig):
    weixin: WeixinConfig = field(
        default=None,
        metadata={'dataclasses_json': {'mm_field': WeixinConfig}}
    )
    db: DbConfig = field(
        default=None,
        metadata={'dataclasses_json': {'mm_field': DbConfig}}
    )
    web: WebConfig = field(
        default=None,
        metadata={'dataclasses_json': {'mm_field': WebConfig}}
    )
    baidu: BaiduConfig = field(
        default=None,
        metadata={'dataclasses_json': {'mm_field': BaiduConfig}}
    )


config = Settings()
config.load('/etc/aab/aab.yaml')
